package com.wlf.admin.system.service;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.wlf.admin.common.dto.CacheKey;
import com.wlf.admin.common.dto.Const;
import com.wlf.admin.common.dto.ParamPage;
import com.wlf.admin.common.util.AjaxBean;
import com.wlf.admin.common.util.AjaxError;
import com.wlf.admin.common.util.JSON;
import com.wlf.admin.system.domain.RoleUser;
import com.wlf.admin.system.domain.SysRole;
import com.wlf.admin.system.domain.SysUser;
import com.wlf.admin.system.mapper.SysUserMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@CacheConfig(cacheNames = CacheKey.user)
public class SysUserService extends ServiceImpl<SysUserMapper, SysUser> {
    @Resource
    private SysRoleService roleService;
    @Resource
    private SysSerialService serialService;
    @Resource
    private SysOrganService organService;

    // 默认密码
    final String defaultPasswd = "000000";

    /**
     * 功能描述: 列表数据
     *
     * @author wlf 2023/9/16 21:08
     */
    public AjaxBean getList(SysUser user, ParamPage paramPage) {
        Page<SysUser> page = this.lambdaQuery()
                .like(StrUtil.isNotBlank(user.getName()), SysUser::getName, user.getName())
                .like(StrUtil.isNotBlank(user.getLoginNo()), SysUser::getLoginNo, user.getLoginNo())
                .page(paramPage.init());
        for (SysUser record : page.getRecords()) {
            List<Long> roleIds = Db.lambdaQuery(RoleUser.class).eq(RoleUser::getUserId, record.getId()).list().stream().map(RoleUser::getRoleId).collect(Collectors.toList());
            record.setRoleList(roleService.lambdaQuery().in(SysRole::getId,
                    roleIds.isEmpty() ? ListUtil.of(-1L) : roleIds).list());
            record.setOrgan(organService.get(record.getOrganId()));
        }
        return AjaxBean.getOkPage(page);
    }

    /**
     * 功能描述: 获取单个
     *
     * @author wlf 2023/9/16 21:08
     */
    @Cacheable(key = "#id")
    public SysUser get(Long id) {
        SysUser user = this.getById(id);
        user.setRoleIdsStr(JSON.toJSONString(Db.lambdaQuery(RoleUser.class).eq(RoleUser::getUserId, id).list()
                .stream().map(RoleUser::getRoleId).collect(Collectors.toList())));
        user.setOrgan(organService.get(user.getOrganId()));
        return user;
    }

    /**
     * 功能描述: 获取当前登录用户信息
     *
     * @author wlf 2023/12/4 14:37
     */
    public SysUser getLoginUser() {
        return SpringUtil.getBean(this.getClass()).get(StpUtil.getLoginIdAsLong());
    }

    /**
     * 功能描述: 删除单个
     *
     * @author wlf 2023/9/16 21:08
     */
    @CacheEvict(key = "#id")
    public AjaxBean del(Long id) {
        checkAdmin(id);
        return AjaxBean.getByBool(this.removeById(id));
    }

    /**
     * 重置密码
     */
    @CacheEvict(key = "#id")
    public AjaxBean reset(Long id) {
        return AjaxBean.getByBool(this.lambdaUpdate()
                .set(SysUser::getPssswd, Const.md5.digestHex16(defaultPasswd))
                .eq(SysUser::getId, id).update(), "密码重置成功,初始密码为:" + defaultPasswd, "");
    }

    /**
     * 功能描述: 批量删除
     *
     * @author wlf 2023/9/16 21:08
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxBean delAll(List<Long> ids) {
        for (Long id : ids) {
            checkAdmin(id);
            SpringUtil.getBean(this.getClass()).del(id);
        }
        return AjaxBean.getOkMsg("删除成功");
    }


    /**
     * 校验是否为Admin用户
     */
    private void checkAdmin(Long id) {
        if (1L == id) {
            AjaxError.getAndThrow("Admin用户不可删除");
        }
    }

    /**
     * 功能描述: 添加用户
     *
     * @author wlf 2023/9/16 21:09
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxBean add(SysUser t) {
        t.setId(IdWorker.getId());
        List<Long> roleIds = JSON.parseArray(HtmlUtil.unescape(t.getRoleIdsStr()), Long.class);
        if (roleIds.isEmpty()) {
            AjaxError.getAndThrow("请至少勾选一个角色信息");
        }
        for (Long roleId : roleIds) {
            RoleUser roleUser = new RoleUser();
            roleUser.setUserId(t.getId());
            roleUser.setRoleId(roleId);
            Db.save(roleUser);
        }
        t.setPssswd(Const.md5.digestHex16(defaultPasswd));
        t.setLoginNo(serialService.getSerial(Const.SerialType.LOGIN_NO));
        t.setCreateTime(LocalDateTime.now());
        return AjaxBean.getByBool(this.save(t));
    }

    /**
     * 功能描述: 更新用户
     *
     * @author wlf 2023/9/16 21:09
     */
    @Caching(
            evict = {
                    @CacheEvict(cacheNames = CacheKey.power, key = "#t.id"),
                    @CacheEvict(key = "#t.id")
            }
    )
    @Transactional(rollbackFor = Exception.class)
    public AjaxBean update(SysUser t) {
        List<Long> roleIds = JSON.parseArray(HtmlUtil.unescape(t.getRoleIdsStr()), Long.class);
        if (roleIds.isEmpty()) {
            AjaxError.getAndThrow("请至少勾选一个角色信息");
        }
        // 先删除
        Db.lambdaUpdate(RoleUser.class).eq(RoleUser::getUserId, t.getId()).remove();
        for (Long roleId : roleIds) {
            RoleUser roleUser = new RoleUser();
            roleUser.setUserId(t.getId());
            roleUser.setRoleId(roleId);
            Db.save(roleUser);
        }
        return AjaxBean.getByBool(this.updateById(t));
    }

    /**
     * 填充表单数据
     */
    public Dict formData() {
        List<SysRole> roleList = roleService.list();
        for (SysRole sysRole : roleList) {
            sysRole.setStatus(!sysRole.getStatus());
        }
        TreeNodeConfig tConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        tConfig.setIdKey("value");
        tConfig.setChildrenKey("children");
        tConfig.setNameKey("name");
        List<Tree<String>> treeList = TreeUtil.build(organService.list(), "0", tConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId().toString());
                    tree.setParentId(treeNode.getPid().toString());
                    tree.setWeight(treeNode.getSort());
                    tree.setName(treeNode.getName());
                    tree.putExtra("disabled", !treeNode.getStatus());
                });
        return Dict.create()
                .set("roleList", roleList)
                .set("organList", treeList)
                ;
    }
}
